package com.flaremars.picker.utils.http.newhttp;

import java.io.File;
import java.io.IOException;
import java.util.Map;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okio.Buffer;
import okio.BufferedSink;
import okio.ForwardingSink;
import okio.Okio;
import okio.Sink;

/**
 * Created by FlareMars on 2016/1/28.
 */
public enum HttpUploadHelper {
    INSTANCE;

    public Call addUploadRequest(Request request,Callback callback) {

        OkHttpClient client = new OkHttpClient.Builder().build();
        Call call = client.newCall(request);
        call.enqueue(callback);
        return call;
    }

    public Call addUploadRequest(String url,Map<String,String> params,String fileFiled,File file,
                                 ProgressListener listener, Callback callback) {
        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
        builder.addFormDataPart(fileFiled, file.getName(), RequestBody.create(MediaType.parse("application/octet-stream"), file));
        for (Map.Entry<String,String> entry : params.entrySet()) {
            builder.addFormDataPart(entry.getKey(),entry.getValue());
        }
        RequestBody requestBody = builder.build();
        Request request = new Request.Builder().
                url(url).
                post(new ProgressRequestBody(requestBody,listener)).
                build();
        return addUploadRequest(request,callback);
    }

    private static class ProgressRequestBody extends RequestBody {
        private final RequestBody requestBody;
        private final ProgressListener progressListener;
        private BufferedSink bufferedSink;

        public ProgressRequestBody(RequestBody requestBody, ProgressListener progressListener) {
            this.requestBody = requestBody;
            this.progressListener = progressListener;
        }

        @Override
        public MediaType contentType() {
            return requestBody.contentType();
        }

        @Override
        public long contentLength() throws IOException {
            return requestBody.contentLength();
        }

        @Override
        public void writeTo(BufferedSink sink) throws IOException {
            if (bufferedSink == null) {
                bufferedSink = Okio.buffer(sink(sink));
            }
            requestBody.writeTo(bufferedSink);
            bufferedSink.flush();

        }

        private Sink sink(Sink sink) {
            return new ForwardingSink(sink) {
                long bytesWritten = 0L;
                long contentLength = 0L;

                @Override
                public void write(Buffer source, long byteCount) throws IOException {
                    super.write(source, byteCount);
                    if (contentLength == 0) {
                        contentLength = contentLength();
                    }
                    bytesWritten += byteCount;
                    progressListener.onProgress(bytesWritten, contentLength, bytesWritten == contentLength);
                }
            };
        }
    }
}
